#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

// 测试用例
struct testCase {
    int n;
    int d;
    vector<vector<int>> line_node;
};

// 父节点表示法
typedef struct node {
    int father;   //父节点
    int weight;   //到父节点的边权值
    int num_son;        //遍历标志
    int max_depth;    //到叶节点的路长
    bool had_cut = false;       //切掉标志
} node, *p_node;

class dTree {
private:
    p_node tree{};
    int max_depth{}, num_node{}, sum{}, queue_head{}, queue_tail{};
    int *leaf_queue;
public:
    dTree(int n, int d);

    dTree(testCase t_case);

    void push(int i);

    int pop();

    int solution();
};

// 测试构造函数
dTree::dTree(int n, int d) {        //构建与初始化树
    this->sum = 0;
    this->queue_head = 0;
    this->queue_tail = 0;
    this->max_depth = d;
    this->num_node = n;
    this->leaf_queue = new int[n];

    // 初始化树的所有节点
    this->tree = new node[n];
    // 根节点
    this->tree[0].father = -1;
    this->tree[0].weight = 0;
    // 循环读取树的节点信息
    for (int i = 0; i < n; i++) {
        int num_son, weight, son_idx;
        cin >> num_son;
        this->tree[i].had_cut = false;
        this->tree[i].num_son = num_son;
        this->tree[i].max_depth = 0;
        // 读取该节点的子节点信息
        for (int j = 0; j < num_son; j++) {
            cin >> son_idx >> weight;
            this->tree[son_idx].father = i;
            this->tree[son_idx].weight = weight;
        }
    }
}

// 重载构造函数, debug用
dTree::dTree(testCase t_case) {
    this->sum = 0;
    this->queue_head = 0;
    this->queue_tail = 0;
    this->max_depth = t_case.d;
    this->num_node = t_case.n;
    this->leaf_queue = new int[t_case.n];

    // 初始化树的所有节点
    this->tree = new node[t_case.n];
    for (int i = 0; i < t_case.n; i++) {
        this->tree[i].weight = -1;
    }

    // 根节点
    this->tree[0].father = -1;
    this->tree[0].weight = 0;
    // 循环读取树的节点信息
    for (int i = 0; i < t_case.n; i++) {
        vector<int> line = t_case.line_node[i];
        int num_son = line[0];
        this->tree[i].had_cut = false;
        this->tree[i].num_son = line[0];
        this->tree[i].max_depth = 0;
        // 读取该节点的子节点信息
        int weight, son_idx;
        int base_shift = 1;
        for (int j = 0; j < num_son; j++) {
            son_idx = line[base_shift + 0];
            weight = line[base_shift + 1];
            base_shift += 2;
            this->tree[son_idx].father = i;
            this->tree[son_idx].weight = weight;
        }
    }
};

void dTree::push(int i) {
    //入队列
    this->leaf_queue[queue_tail++] = i;
};

int dTree::pop() {
    //出队列
    int temp = leaf_queue[queue_head++];
    return temp;
};

int dTree::solution() {
    //剪切
    // 检测叶节点, 入队列
    for (int i = this->num_node - 1; i >= 0; i--) {
        if (this->tree[i].num_son == 0) {
            push(i);
        }
    }

    while (this->queue_head != this->queue_tail) {
        int node_idx = pop();
        int node_weight = this->tree[node_idx].weight;
        int parent_idx = this->tree[node_idx].father;
        // 如果父节点的没有被切除过 而且 该父节点的最深路径长超过最大深度
        if (not this->tree[parent_idx].had_cut && this->tree[node_idx].max_depth + node_weight > this->max_depth) {
            // 切除该节点
            this->tree[parent_idx].had_cut = true;
            parent_idx = this->tree[parent_idx].father;
            this->sum++;
            // 父节点没有被切除 且 父节点最深路径长小于当前深度
        } else if (this->tree[node_idx].had_cut == 0 &&
                   this->tree[parent_idx].max_depth < this->tree[node_idx].max_depth + node_weight) {
            this->tree[parent_idx].max_depth = this->tree[node_idx].max_depth + node_weight;
        }
        // 如果更新后父节点是子节点
        if (--this->tree[parent_idx].num_son == 0)
            push(parent_idx);
    }
    cout << this->sum;
    return this->sum;
}

int main() {

    testCase case1 = {
            .n = 5,
            .d = 5,
    };
    case1.line_node = vector<vector<int>>{
            vector<int>{3, 1, 4, 2, 9, 3, 2},
            vector<int>{0},
            vector<int>{1, 4, 5},
            vector<int>{0},
            vector<int>{0},
    };

    dTree test(case1);
    test.solution();
    return 0;
}